/* eslint-disable no-inline-comments */
/************************************************************************************************
 *   深圳市摩西尔电子有限公司 @版本所有@
 *
 *   此文件用于走点页面填充功能
 *
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.5.5
 *      内容 : 所有代码
 *************************************************************************************************/
/* exported mc_get_rule_by_dot*/
/* exported mc_quick_fill_apply */

/* global mc_js_map  */
/* global mc_sdk_param  */

/************************************************************************************************
 * 类型:
 *    构造函数
 * 功能:
 *    根据已知走点,生成多套规则下的数据,共选择
 * 参数:
 *    NA
 * 返回：
 *   NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.5.6
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_get_rule_by_dot() {
    var obj_map_point = new mc_js_map();
    // 已知走点数据
    var m_ary_dot_data = [];

    // 已知模组参数
    // 模组宽度
    var m_ui_mod_w = 0;
    // 模组高度
    var m_ui_mod_h = 0;
    // 模组芯片通道数
    var m_ui_mod_ic = 0;
    // 模组行长对齐值
    var m_ui_mod_scanalign = 0;
    // 模组设置的行扫数
    var m_ui_scan_cnt = 0;
    // 模组单扫有效灯珠数
    var m_ui_scan_len = 0;
    // 模组数据组类型;
    var m_ui_grp_mod = 0;
    // 模组数据组数;
    var m_ui_grp_cnt = 0;
    // 模组颜色
    var m_ary_str_color = [];
    // 由于confim异步的原因所以定下观察模式,如果此值为false部分性函数失效,统一返回false
    var m_b_is_success = true;
    // 补点结果
    var m_b_fill_ok = true;

    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *    将已知走点存入,解析为内部识别数据
     * 参数:
     *    @param {promises<Array>} ary_dot 已知走点坐标数组
     *    @param {promises<Function>} fn_callback 回调函数
     * 返回：
     *   NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_set_dot_data(ary_dot, fn_callback) {
        if ("function" !== typeof fn_callback) {
            return;
        }
        if (!Array.isArray(ary_dot) || 0 > ary_dot.length) {
            fn_callback();
            return;
        }
        for (var idx_str = 0; idx_str < (m_ui_grp_cnt * m_ui_grp_mod); idx_str++) {
            var ary_str_val = ary_dot[idx_str];

            m_ary_dot_data.push([]);
            if (!ary_str_val) {
                continue;
            }
            // 根据数据线创建数组
            for (var idx_scan = 0; idx_scan < ary_str_val.length; idx_scan++) {
                var ary_scan_val = ary_str_val[idx_scan];

                m_ary_dot_data[idx_str].push([]);
                for (var idx_pix = 0; idx_pix < ary_scan_val.length; idx_pix++) {
                    // 获取页面走点数据,根据行扫获取没扫的每个点 页面数据冲1开始所以每个数值均需-1
                    var obj_point_data = ary_scan_val[idx_pix];
                    var ary_scan_data = m_ary_dot_data[idx_str][idx_scan];

                    if (!obj_point_data) {
                        ary_scan_data.push(obj_point_data);
                        continue;
                    }
                    var ui_img_x = Number(obj_point_data.x - 1);
                    var ui_img_y = Number(obj_point_data.y - 1);
                    var str_color = obj_point_data.color;
                    var obj_loc_point = {
                        img_x: ui_img_x,
                        img_y: ui_img_y,
                        color: str_color
                    };
                    var ui_invalid_cnt = Number(obj_point_data.invalid_cnt);

                    for (var idx_add_invalid = 0; idx_add_invalid < ui_invalid_cnt; idx_add_invalid++) {
                        ary_scan_data.push({
                            img_x: 0,
                            img_y: 0,
                            color: "V"
                        });
                    }
                    ary_scan_data.push(obj_loc_point);

                    var str_know_point = ui_img_x + "_" + ui_img_y + "_" + str_color;

                    obj_map_point.set(str_know_point, 1);
                }
            }
        }

        mc_dot_is_ok(fn_callback);
        return;
    }
    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *    判断行扫数量是否异常
     * 参数:
     *    @param {promises<Function>} fn_callback 回调函数
     * 返回：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_dot_is_ok(fn_callback) {
        for (var idx_grp_idx = 0; idx_grp_idx < m_ary_dot_data.length; idx_grp_idx++) {
            if (m_ary_dot_data[idx_grp_idx].length > m_ui_scan_cnt) {
                parent.mc_confirm_popout({
                    msg: "MC_LANG_SCAN_CNT_ERROR",
                    btn: ["MC_LANG_DELETE", "MC_LANG_WALK_ON_POINT"],
                    confirm_callback: "confirm_callback",
                    cancel_callback: "cancel_callback",
                    close_iframe: true
                });
                return;
            }
        }

        function confirm_callback() {  // eslint-disable-line
            mc_delet_scan_extra();
            fn_callback();
        }

        function cancel_callback() { // eslint-disable-line
            mc_end_file();
            fn_callback();
        }

        fn_callback();
    }
    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *    函数失效化,当不满住流程中某些硬性条件时整个流程失效
     * 参数:
     *    NA
     * 返回：
     *    NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_end_file() {
        m_b_is_success = false;
    }

    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *    将已知模组信息存入
     * 参数:
     *    @param {promises<Array>} obj_mod_msg 模组基本信息
     * 返回：
     *   @returns {Promise<boolean>} 存入结果
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_set_mod_msg(obj_mod_msg) {
        if (Array.isArray(obj_mod_msg) || "object" !== typeof obj_mod_msg) {
            return false;
        }
        // 模组宽度
        m_ui_mod_w = Number(obj_mod_msg.ui_mod_w);
        // 模组高度
        m_ui_mod_h = Number(obj_mod_msg.ui_mod_h);
        // 模组芯片通道数
        m_ui_mod_ic = Number(obj_mod_msg.ui_ic_channels);
        // 模组行长对齐值
        m_ui_mod_scanalign = Number(obj_mod_msg.ui_scanalign);
        // 模组设置的行扫数
        m_ui_scan_cnt = Number(obj_mod_msg.ui_scan_cnt);
        // 模组数据组类型
        m_ui_grp_mod = Number(obj_mod_msg.ui_grp_mod);
        // 模组数据组数
        m_ui_grp_cnt = Number(obj_mod_msg.ui_grp_cnt);
        // 模组单扫长度(参考值)
        m_ui_scan_len = Number(obj_mod_msg.ui_scan_len);
        // 模组颜色
        m_ary_str_color = obj_mod_msg.ary_color;
        if (isNaN(m_ui_mod_w) || 0 >= m_ui_mod_w ||
            isNaN(m_ui_mod_h) || 0 >= m_ui_mod_h ||
            isNaN(m_ui_mod_ic) || 0 >= m_ui_mod_ic ||
            isNaN(m_ui_scan_cnt) || 0 >= m_ui_scan_cnt ||
            isNaN(m_ui_grp_mod) || 0 >= m_ui_grp_mod ||
            isNaN(m_ui_grp_cnt) || 0 >= m_ui_grp_cnt ||
            isNaN(m_ui_scan_len) || 0 >= m_ui_scan_len
        ) {
            mc_end_file();
            return false;
        }
        if (1 === m_ui_grp_mod) {
            m_ui_scan_len *= m_ary_str_color.length;
        }
        if (isNaN(m_ui_mod_scanalign) || 0 >= m_ui_mod_scanalign) {
            m_ui_mod_scanalign = 1;
        }
        return true;
    }

    /* ******************* 补点规则获取 ***************************************************** */
    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *     执行补点命令
     * 参数:
     *    @param {Promise<Number>} ui_select_str_idx 指定填充数据线
     *    @param {Promise<Function>} fn_callback 执行结束的回调函数
     * 返回：
     *   NA
     *  备注:
     *      1.由于目前只有一条补点规则,当出现多条时,需要明确使用规则才可执行补点命令 2020.5.6
     *      2.添加第二条规则 ( 根据第一条规则不可取时则使用第二条规则 ) 2021.11.25
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_fill_line(ui_select_str_idx, fn_callback) {
        if ("function" !== typeof fn_callback) {
            return;
        }
        if (!m_b_is_success || 0 >= m_ary_dot_data.length) {
            fn_callback();
            return;
        }
        for (var idx_str = 0; idx_str < m_ary_dot_data.length; idx_str++) {
            var ary_scan_val = m_ary_dot_data[idx_str];

            if (-1 !== ui_select_str_idx) {
                ary_scan_val = m_ary_dot_data[ui_select_str_idx - 1];
            }

            for (var idx_scan = 0; idx_scan < ary_scan_val.length; idx_scan++) {
                var ary_scan = ary_scan_val[idx_scan];
                var ary_fill_data = mc_supply_point_rule_1(ary_scan);

                if (!ary_fill_data) {
                    ary_fill_data = mc_supply_point_rule_2(ary_scan);
                }

                if (!ary_fill_data) {
                    continue;
                }
                ary_scan_val[idx_scan] = ary_fill_data;
            }
            if (-1 !== ui_select_str_idx) {
                break;
            }
        }
        fn_callback();

        // mc_loading_wait_remove();
        // return;
    }

    /* ******************* 补点区域 ***************************************************** */

    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *     补点(单扫) 规则1
     * 参数:
     *    @param {Promise<Array>} date 当前界面所描的点 根据当前描点的规则 生成规则的单扫的点数
     * 返回：
     *   @param {Promise<boolean>} false 补点失败
     *   @param {Promise<Array>} arr_finall_date 成功补点后的数据
     * 备注:
     *  针对:字母代表每个值存在的规律 ( 适用于任何一处起始 ) (回车:换行或换列)
     *      1.ABCDE...顺序
     *      2.AABBCCDD.. 叠加(可多个AAAAA...)
     *      3.AABB空空(回车)CCDD空空(回车)EEFF  (可多个重叠AAAAA...)
     *      4.A空空B空空C空空D 回车 E空空F空空G空空H空空 ( 可叠加再空如 : AB空空CD空空 回车 EF空空GH空空 )
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 李智明
     *      时间 : 2021.3.1
     *      内容 : 所有代码
     ************************************************************************************************/


    function mc_supply_point_rule_1(date) {
        var arr_point_date = date;
        // 最终输出结果数组
        var arr_finall_date = [];
        //  新增点的数组
        var arr_result = [];
        // 临时存放新点的数组
        var arr_temporary_point = [];
        // 分段数组
        var arr_division_result = [];
        // 总段数
        var ui_paragraph_count = 0;
        // 设置 G0点数
        var ui_G0_count = 0;
        // 组间偏差
        var ui_group_offsetX_val = 0;
        var ui_group_offsetY_val = 0;
        var ui_group_index = 0;
        // 组内点索引i
        var ui_within_group_idx = 0;
        // 总组数Gt
        var ui_all_group_Gt = 0;
        // 单扫的单组有效点数
        var single_group_valid_Lamp_count = 0;
        // 创建新节点
        var Xn = 0;
        var Yn = 0;
        var Cn = "V";
        // 规律数组三个信息
        var X0 = 0;
        var Y0 = 0;
        var C0 = 0;
        // 保存点
        var str_point = "";
        // 获取三个差值数组对象
        var obj_diffr_val = {};
        // 多组数据数组
        var arr_group_point = [];
        // 点信息
        var XI = 0;
        var YI = 0;
        // 已经获取最新XI 和 YI
        var b_get_xyI = false;

        // 判断有效点  检测当前有效点数量 检验是否存在空点
        if (!mc_jungle_efficient_point(arr_point_date)) {
            return false;
        }


        // 将描点数组进行分段
        arr_division_result = mc_split_arr_point(arr_point_date);
        // 判断 总段数
        if (1 === arr_division_result.length) {
            ui_paragraph_count = 1;
            // 总段数为1
            obj_diffr_val = mc_get_three_law_arr(arr_division_result, arr_division_result);
            // 第一段的长度 统一生成的差值数组的
            ui_G0_count = obj_diffr_val.arr_x_change.length;
            // 获取 gt
            ui_all_group_Gt = mc_get_single_parp_val();
            ui_within_group_idx = 0;
        } else {
            // 组数
            arr_group_point = mc_get_ary_chunk(arr_division_result);
            if (!arr_group_point || (!arr_group_point.ui_offset_x && !arr_group_point.ui_offset_y)) {
                // 清空结果数组
                return false;
            }
            // 偏差 Xd Yd
            ui_group_offsetX_val = arr_group_point.ui_offset_x;
            ui_group_offsetY_val = arr_group_point.ui_offset_y;
            obj_diffr_val = mc_get_three_law_arr(arr_group_point.ary_segment_grp[0], arr_division_result);
            // 获取 gt
            ui_all_group_Gt = mc_get_multi_parp_val();
            // 设置当前Gi
            ui_group_index = arr_group_point.ary_segment_grp.length - 1;
            var ui_group = arr_group_point.ary_segment_grp;
            var arr_change = [];

            arr_division_result = [];
            // 转换结果数组数据
            for (var group_all_idx = 0; group_all_idx < ui_group.length; group_all_idx++) {
                arr_change = [];
                for (var parp_each_idx = 0; parp_each_idx < ui_group[group_all_idx].length; parp_each_idx++) {
                    for (var each_point_idx = 0; each_point_idx < ui_group[group_all_idx][parp_each_idx]
                        .length; each_point_idx++) {
                        arr_change.push(ui_group[group_all_idx][parp_each_idx][each_point_idx]);
                    }
                }
                arr_division_result.push(arr_change);
            }

            ui_within_group_idx = mc_get_within_grp_idx(arr_division_result[arr_division_result.length - 1]);
            ui_G0_count = mc_first_grp_pnt(arr_division_result[0]);
        }

        //获取 ui_within_group_idx
        function mc_get_within_grp_idx(arr) {
            var ui_within_cnt = 0;

            // 最后一组
            for (var last_group = 0; last_group < arr.length; last_group++) {
                ui_within_cnt++;
            }
            return ui_within_cnt;
        }

        // 获取第一组的点数
        function mc_first_grp_pnt(arr) {
            var ui_cnt = 0;

            for (var first_group = 0; first_group < arr.length; first_group++) {
                // 获取第一组的点数
                ui_cnt++;
            }
            return ui_cnt;
        }

        // 获取单组单段有效点
        function mc_get_single_parp_val() {
            for (var idx = 0; idx < arr_division_result[0].length; idx++) {
                if ("V" !== arr_division_result[0][idx].color) {
                    single_group_valid_Lamp_count++;
                }
            }
            // 防止生成点数不够
            single_group_valid_Lamp_count--;
            return Math.ceil(m_ui_scan_len / single_group_valid_Lamp_count);
        }

        // 获取单组多段有效点
        function mc_get_multi_parp_val() {
            for (var group_idx = 0; group_idx < arr_group_point.ary_segment_grp[0].length; group_idx++) {
                for (var parp_idx = 0; parp_idx < arr_group_point.ary_segment_grp[0][group_idx]
                    .length; parp_idx++) {
                    if ("V" !== arr_group_point.ary_segment_grp[0][group_idx][parp_idx].color) {
                        single_group_valid_Lamp_count++;
                    }
                }
            }
            return Math.ceil(m_ui_scan_len / single_group_valid_Lamp_count);
        }

        // 比较 I与G0
        function mc_jungle_I_GO_point() {
            // I<G0点数?
            if (ui_within_group_idx < ui_G0_count) {
                Xn = 0;
                Yn = 0;
                Cn = "V";
                // 三个信息值
                X0 = obj_diffr_val.arr_x_change[ui_within_group_idx];
                Y0 = obj_diffr_val.arr_y_change[ui_within_group_idx];
                C0 = obj_diffr_val.arr_clr_order[ui_within_group_idx];
                b_get_xyI = false;
                if ("V" === C0) {
                    mc_add_new_point();
                } else {
                    if (0 !== ui_within_group_idx || 1 === ui_paragraph_count) {
                        // 取出结果数组 最后个有效值XI YI
                        for (var i = arr_division_result.length - 1; 0 <= i; i--) {
                            for (var j = arr_division_result[i].length - 1; 0 <= j; j--) {
                                if ("V" === arr_division_result[i][j].color) {
                                    continue;
                                } else {
                                    XI = arr_division_result[i][j].img_x;
                                    YI = arr_division_result[i][j].img_y;
                                    b_get_xyI = true;
                                    break;
                                }
                            }
                            if (b_get_xyI) {
                                break;
                            }
                        }

                        // 判断当前YI等于模组高度 (仅仅判断高度)
                        // if (YI === m_ui_mod_h - 1) {
                        //     if (1 === ui_paragraph_count) {
                        //         var data = [];
                        //         arr_division_result.map(function (val, index, arr_division_result) {
                        //             data = data.concat(val);
                        //         });
                        //         var arr_get_rule = mc_get_rule_val_by_segment(data);
                        //         if (arr_get_rule) {
                        //             var ui_scan_type = arr_get_rule[0];
                        //             var ui_scan_position = arr_get_rule[1];
                        //             if (0 < ui_scan_type) {
                        //                 if (ui_scan_position > (m_ui_mod_w / 2)) {
                        //                     ui_group_offsetX_val = 1;
                        //                 } else {
                        //                     ui_group_offsetX_val = -1;
                        //                 }
                        //             }
                        //         }
                        //         // 赋值
                        //         Xn = (Number(XI) - Number(ui_group_offsetX_val) + Number(X0) + Number(m_ui_mod_w)) % (Number(m_ui_mod_w));
                        //         Yn = (Number(YI) + Number(Y0) + Number(m_ui_mod_h)) % (Number(m_ui_mod_h));
                        //         Cn = C0;
                        //     };
                        // } else {
                        // 赋值
                        Xn = (Number(XI) + Number(X0) + Number(m_ui_mod_w)) % (Number(m_ui_mod_w));
                        Yn = (Number(YI) + Number(Y0) + Number(m_ui_mod_h)) % (Number(m_ui_mod_h));
                        Cn = C0;
                        // }
                    } else {
                        // 取出结果上一组第i点信息
                        XI = arr_division_result[arr_division_result.length - 1][ui_within_group_idx].img_x;
                        YI = arr_division_result[arr_division_result.length - 1][ui_within_group_idx].img_y;
                        // 赋值
                        Xn = (Number(XI) + Number(ui_group_offsetX_val) + Number(X0) + Number(m_ui_mod_w)) % (Number(m_ui_mod_w));
                        Yn = (Number(YI) + Number(ui_group_offsetY_val) + Number(Y0) + Number(m_ui_mod_h)) % (Number(m_ui_mod_h));
                        Cn = C0;
                    }
                    //判断是否存在  Sn-------------------------------------------
                    str_point = Xn + "_" + Yn + "_" + Cn;

                    if (obj_map_point.get(str_point)) {
                        // 清空结果数组
                        arr_finall_date = [];
                        arr_temporary_point = [];
                        return;
                    }
                    arr_temporary_point.push(str_point);
                    // obj_map_point.set(str_point, 1);
                    // 添加新点
                    mc_add_new_point();
                }
            } else {
                ui_group_index++;
                ui_within_group_idx = 0;
                // Gi<Gt ?
                if (ui_group_index < ui_all_group_Gt) {
                    mc_jungle_I_GO_point();
                } else {
                    // 判断长度书否是A或C整数倍
                    mc_arr_result_inte_mult();
                }
            }
        }

        // 模组不存在新创建的点则添加到后面
        function mc_add_new_point() {
            // 新节点
            var obj_new_point = {
                img_x: 0,
                img_y: 0,
                color: "V"
            };

            // 将新创建点添加到结果数组
            obj_new_point.img_x = Xn;
            obj_new_point.img_y = Yn;
            obj_new_point.color = Cn;

            // 判断当前已存组里的点的个数
            if (0 === ui_within_group_idx) {
                arr_division_result.push(arr_result);
                arr_division_result[arr_division_result.length - 1].push(obj_new_point);
                arr_result = [];
            } else {
                arr_division_result[arr_division_result.length - 1].push(obj_new_point);
            }

            // 有效点的数量
            var ui_effect_point = 0;

            for (var i = 0; i < arr_division_result.length; i++) {
                for (var kdx = 0; kdx < arr_division_result[i].length; kdx++) {
                    if ("V" !== arr_division_result[i][kdx].color) {
                        ui_effect_point++;
                    }
                }
            }
            // 结果数组有效点是否大于L
            if (ui_effect_point >= m_ui_scan_len) {
                mc_arr_result_inte_mult();
            } else {
                ui_within_group_idx++;
                mc_jungle_I_GO_point();
            }
        }

        // 结果数组是否是A,C整数倍
        function mc_arr_result_inte_mult() {
            arr_finall_date = [];
            for (var i = 0; i < arr_division_result.length; i++) {
                for (var z = 0; z < arr_division_result[i].length; z++) {
                    arr_finall_date.push(arr_division_result[i][z]);
                }
            }
            mc_jungle_add_fake_point();
        }

        // 是否添加虚点
        function mc_jungle_add_fake_point() {
            //不是整数倍 则添加 ----------------------------------------------------
            if (0 !== arr_finall_date.length % m_ui_mod_ic || 0 !== arr_finall_date.length % m_ui_mod_scanalign) {
                arr_finall_date.push({
                    img_x: 0,
                    img_y: 0,
                    color: "V"
                });
                mc_jungle_add_fake_point();
            }
        }

        mc_jungle_I_GO_point();

        if (0 !== arr_finall_date.length) {
            // 判断当前点与整组点是否存在相同
            for (var idx_point = 0; idx_point < arr_temporary_point.length; idx_point++) {
                var str_current_point = arr_temporary_point[idx_point];

                for (var idx_each_point = 0; idx_each_point < arr_temporary_point.length; idx_each_point++) {
                    if (str_current_point === arr_temporary_point[idx_each_point] && idx_each_point !== idx_point) {
                        return false;
                    }
                }
            }

            // 添加点到对象
            for (var idx = 0; idx < arr_temporary_point.length; idx++) {
                obj_map_point.set(arr_temporary_point[idx], 1);
            }
            return arr_finall_date;
        }
        return false;
    }


    // 获取差值结果
    function mc_get_three_law_arr(arr_all, arr_division_result) {
        var arr_x_change = [];
        var arr_y_change = [];
        var arr_clr_order = [];
        var obj = {
            arr_x_change: "",
            arr_y_change: "",
            arr_clr_order: ""
        };
        var arr_group = arr_all;
        // 定义
        var x_change;
        var y_change;
        var RGB_change;
        var arr_parp = [];
        // 定义当前有效值的下标
        var idx_real = 0;

        // 多组数据
        if (1 < arr_division_result.length) {
            // 组段数 多组多段
            if (1 !== arr_group.length) {
                for (var parp_idx = 0; parp_idx < arr_group.length; parp_idx++) {
                    for (var point_idx = 0; point_idx < arr_group[parp_idx].length; point_idx++) {
                        arr_parp.push(arr_group[parp_idx][point_idx]);
                    }
                }
            } else {
                // 多组单段
                for (var fst_parp_idx = 0; fst_parp_idx < arr_group[0].length; fst_parp_idx++) {
                    arr_parp.push(arr_group[0][fst_parp_idx]);
                }
            }
            arr_x_change.push(0);
            arr_y_change.push(0);
            arr_clr_order.push(arr_parp[0].color);
            for (var first_idx = 1; first_idx < arr_parp.length; first_idx++) {
                if ("V" !== arr_parp[first_idx].color) {
                    x_change = arr_parp[first_idx].img_x - arr_parp[idx_real].img_x;
                    y_change = arr_parp[first_idx].img_y - arr_parp[idx_real].img_y;
                    RGB_change = arr_parp[first_idx].color;
                    idx_real = first_idx;
                } else {
                    x_change = 0;
                    y_change = 0;
                    RGB_change = "V";
                }
                arr_x_change.push(x_change);
                arr_y_change.push(y_change);
                arr_clr_order.push(RGB_change);
            }
        } else {
            // 单组单段数据
            // 判断第一个值
            var arr_one = mc_get_first_offset(arr_group[0]);

            arr_x_change.push(arr_one[0]);
            arr_y_change.push(arr_one[1]);
            arr_clr_order.push(arr_one[2]);

            for (var t = 1; t < arr_group[0].length; t++) {
                // 上个值是虚点
                if ("V" === arr_group[0][t - 1].color) {
                    x_change = 0;
                    y_change = 0;
                    RGB_change = "V";
                }
                // 上个值不是虚点 当前值是虚点
                if ("V" !== arr_group[0][t - 1].color && "V" === arr_group[0][t].color) {
                    // idx_real = t
                    x_change = 0;
                    y_change = 0;
                    RGB_change = "V";
                }
                // 上个值不是虚点 当前值不是虚点
                if ("V" !== arr_group[0][t - 1].color && "V" !== arr_group[0][t].color) {
                    x_change = Number(arr_group[0][t].img_x) - Number(arr_group[0][t - 1].img_x);
                    y_change = Number(arr_group[0][t].img_y) - Number(arr_group[0][t - 1].img_y);
                    idx_real = t;
                    RGB_change = arr_group[0][t].color;
                }
                // 上个值是虚点 下当前值是虚点
                if ("V" === arr_group[0][t - 1].color && "V" !== arr_group[0][t].color && 1 !== t) {
                    x_change = Number(arr_group[0][t].img_x) - Number(arr_group[0][idx_real].img_x);
                    y_change = Number(arr_group[0][t].img_y) - Number(arr_group[0][idx_real].img_y);
                    RGB_change = arr_group[0][t].color;
                }
                arr_x_change.push(x_change);
                arr_y_change.push(y_change);
                arr_clr_order.push(RGB_change);
                // 最后值进行判断
                if (t === arr_group[0].length - 1) {
                    break;
                }
            }
        }
        obj.arr_x_change = arr_x_change;
        obj.arr_y_change = arr_y_change;
        obj.arr_clr_order = arr_clr_order;
        return obj;
    }

    // 获取第一组偏差值
    function mc_get_first_offset(arr) {
        var ui_first_x = arr[0].img_x;
        var ui_first_y = arr[0].img_y;
        var ui_last_x = arr[arr.length - 1].img_x;
        var ui_last_y = arr[arr.length - 1].img_y;

        if (0 < ui_first_x - ui_last_x && ui_first_y === ui_last_y) {
            return [-1, 0, arr[0].color];
        }

        if (0 > ui_first_x - ui_last_x && ui_first_y === ui_last_y) {
            return [1, 0, arr[0].color];
        }

        if (0 < ui_first_y - ui_last_y && ui_first_x === ui_last_x) {
            return [0, -1, arr[0].color];
        }

        if (0 > ui_first_y - ui_last_y && ui_first_x === ui_last_x) {
            return [0, 1, arr[0].color];
        }
        return [-1, -1, -1];
    }


    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *     补点(单扫) 规则2
     * 参数:
     *    @param {Promise<Array>} arr_init 当前界面所描的点 根据当前描点的规则 生成规则的单扫的点数
     * 返回：
     *   @return {Promise<boolean>} false 补点失败
     *   @return {Promise<Array>} arr_finall_date 成功补点后的数据
     *  备注:
     *  针对: ( (14,0)(15,0)(12,0)(13,0)(10,0)(11,0) => 以两个(或多个)连续点相同方向为一段向本段反方向不断续添加补点)
     *      如:DBCA HGFE
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 李智明
     *      时间 : 2021.11.25
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_supply_point_rule_2(arr_init) {
        var arr_data = JSON.parse(JSON.stringify(arr_init));
        // 判断有效点  检测当前有效点数量 检验是否存在空点
        var ui_curr_use_point = mc_jungle_efficient_point(arr_data);

        if (!ui_curr_use_point) {
            return false;
        }

        // 是否符合规则
        var obj_if_run = mc_if_conform_to_rules(arr_data);
        // 分段数据寻找规律

        if (!obj_if_run) {
            return false;
        }
        // 获取参数
        var arr_rule_val = mc_get_point(arr_data, obj_if_run, ui_curr_use_point);


        return arr_rule_val;
    }


    //  返回根据规则后的数据 !!!!! 暂时直接补全 不管前面的虚点是如何设置的
    function mc_get_point(arr_data, obj_param, ui_curr_p_cnt) {
        // 差值数组
        var arr_diff = obj_param.parp_diff;
        // 段长度
        var ui_parp_len = arr_diff.length;
        // 记录当前用段第几个
        var ui_idx = 0;
        // 方向  1:向左/向上 -1:向右/向下
        var ui_direct = arr_diff[0];
        // 初始添加的参数
        var ui_init = obj_param.increase_decline;
        // 添加的时候记录上一个值
        // var ui_prep = 0;
        // 横向还是纵向补齐
        var str_type = obj_param.deal_type;
        // 需补齐的数量
        var ui_need_add_cnt = m_ui_scan_len - ui_curr_p_cnt;

        // 获取当前初始数组的最后一个点
        var obj_last_p = {};
        // 获取最后添加的最后一个点
        var obj_add_last_p = {};
        // 存添加的点
        var arr_add_point = [];

        for (var id = 0; id < arr_data.length; id++) {
            var each_p = arr_data[id];

            // 拿x的点对比
            if ("x" === str_type) {
                var x_each = each_p.img_x;

                if (x_each === ui_init) {
                    obj_last_p = each_p;
                    break;
                }
            } else {
                // 拿y的点对比
                var y_each = each_p.img_y;

                if (y_each === ui_init) {
                    obj_last_p = each_p;
                    break;
                }
            }
        }

        // 添加需补齐的点
        for (var idx = 0; idx < ui_need_add_cnt; idx++) {
            var obj_point = {
                img_x: 0,
                img_y: 0,
                color: obj_param.clr
            };

            // 第一个先加减段长度 后面则使用差值数组
            if (0 === idx) {
                // 同行或同列
                if ("x" === str_type) {
                    obj_point.img_y = obj_last_p.img_y;
                    if (0 < ui_direct) {
                        obj_point.img_x = (ui_init - ui_parp_len + m_ui_mod_w) % m_ui_mod_w;
                        // ui_prep = obj_point.img_x;
                    } else {
                        obj_point.img_x = (ui_init + ui_parp_len + m_ui_mod_w) % m_ui_mod_w;
                        // ui_prep = obj_point.img_x;
                    }
                } else {
                    obj_point.img_x = obj_last_p.img_x;
                    if (0 < ui_direct) {
                        obj_point.img_y = (ui_init - ui_parp_len + m_ui_mod_h) % m_ui_mod_h;
                        // ui_prep = obj_point.img_y;
                    } else {
                        obj_point.img_y = (ui_init + ui_parp_len + m_ui_mod_h) % m_ui_mod_h;
                        // ui_prep = obj_point.img_y;
                    }
                }
            } else {
                // 添加差值数组的数值 获取数组最后一个有效值的点
                if ("x" === str_type) {
                    obj_point.img_y = obj_last_p.img_y;
                    obj_point.img_x = (obj_add_last_p.img_x + arr_diff[ui_idx] + m_ui_mod_w) % m_ui_mod_w;
                } else {
                    obj_point.img_x = obj_last_p.img_x;
                    obj_point.img_y = (obj_add_last_p.img_y + arr_diff[ui_idx] + m_ui_mod_h) % m_ui_mod_h;
                }

                ui_idx += 1;
                if (ui_idx === ui_parp_len) {
                    ui_idx = 0;
                }
            }
            arr_data.push(obj_point);
            obj_add_last_p = JSON.parse(JSON.stringify(obj_point));
            var str_point = obj_point.img_x + "_" + obj_point.img_y + "_" + obj_point.color;

            if (obj_map_point.get(str_point)) {
                return false;
            }
            arr_add_point.push(obj_point);
        }

        mc_get_imagin_p(arr_data);

        function mc_get_imagin_p(arr) {
            if (0 !== arr.length % m_ui_mod_ic || 0 !== arr.length % m_ui_mod_scanalign) {
                arr.push({
                    img_x: 0,
                    img_y: 0,
                    color: "V"
                });
                mc_get_imagin_p(arr);
            }
        }


        if (!mc_exict_same(arr_data)) {
            return false;
        }

        function mc_exict_same(arr) {
            // 遍历生成数组 看是否出现一致
            for (var id_all = 0; id_all < arr.length; id_all++) {
                var obj_fin_each = arr[id_all];
                var str_c_x = obj_fin_each.img_x;
                var str_c_y = obj_fin_each.img_y;
                var str_rgb = obj_fin_each.color;

                if ("V" === str_rgb) {
                    continue;
                }

                for (var id_jgl = 0; id_jgl < arr.length; id_jgl++) {
                    var obj_jungle_each = arr[id_jgl];
                    var str_jungle_rgb = obj_jungle_each.color;

                    if (id_all === id_jgl || "V" === str_jungle_rgb) {
                        continue;
                    }

                    var str_j_x = obj_jungle_each.img_x;
                    var str_j_y = obj_jungle_each.img_y;

                    if (str_c_x === str_j_x && str_c_y === str_j_y) {
                        return false;
                    }
                }
            }

            return true;
        }


        // 添加点到对象
        for (var id_f = 0; id_f < arr_add_point.length; id_f++) {
            var obj_each_p = arr_add_point[id_f];
            var str_set_p = "";

            if ("V" !== obj_each_p.color) {
                str_set_p = obj_each_p.img_x + "_" + obj_each_p.img_y + "_" + obj_each_p.color;
                obj_map_point.set(str_set_p, 1);
            }
        }
        return arr_data;
    }


    // 检测是否符合规则 获取规则需要的参数进行填充
    function mc_if_conform_to_rules(arr_data) {
        // 规则1 必须出现x或y一致 即同行或同列
        var ui_cnt = arr_data.length;
        var arr_all_x = new Array(ui_cnt);
        var arr_all_y = new Array(ui_cnt);
        var obj_return = {
            deal_type: "", //处理x或y参数
            parp_diff: "", // 差值数组
            increase_decline: "",//最大值或最小值 用于接着填充参数(递增或递减)
            clr: "" // 当前补充的颜色
        };
        // 获取所有x,y

        for (var id_r1_x = 0; id_r1_x < ui_cnt; id_r1_x++) {
            var each_r = arr_data[id_r1_x].color;

            if ("V" === each_r) {
                continue;
            }


            var each = arr_data[id_r1_x];

            arr_all_x[id_r1_x] = each.img_x;
            arr_all_y[id_r1_x] = each.img_y;
            obj_return.clr = each_r;
        }

        // 比较 一致的是x还是y
        var x_y_result = mc_get_x_or_y_rule(arr_all_x, arr_all_y);

        if (!x_y_result[0]) {
            return false;
        }

        obj_return.deal_type = x_y_result[1];

        // 规则2 必须是符合描点规则 如(-1,3,-1,3,-1 || -1,-1,-1,-3,-1,-1,-1) !!!目前处理必须连续
        var arr_param_result = mc_get_param_by_rule(arr_data, x_y_result[1]);

        if (!arr_param_result[0]) {
            return false;
        }

        // 获取规则数组
        obj_return.parp_diff = arr_param_result[1];

        // 获取当前是递增还是递减
        obj_return.increase_decline = mc_get_increase_decline(arr_param_result[1], arr_param_result[2]);


        return obj_return;
    }

    // 获取当前是递增还是递减
    function mc_get_increase_decline(arr_diff, arr_new) {
        var ui_first_diff = arr_diff[0];
        // var ui_first = arr_new[0];
        var ui_return = 0;
        var each = 0;
        //当前是取最大还是最小 1取最小 -1取最大
        // var ui_direct = 1;

        if (0 < ui_first_diff) {
            // 得出最小值

            for (var key = 0; key < arr_new.length; key++) {
                each = arr_new[key];
                if (0 === key) {
                    ui_return = each;
                    continue;
                }

                if (ui_return > each) {
                    ui_return = each;
                }
            }
        } else {
            // 得出最大值

            for (var idx = 0; idx < arr_new.length; idx++) {
                each = arr_new[idx];
                if (0 === idx) {
                    ui_return = each;
                    continue;
                }

                if (ui_return < each) {
                    ui_return = each;
                }
            }

            // ui_direct = -1;
        }
        // return [ui_direct, ui_return];
        return ui_return;
    }

    // 根据已知处理x还是y 获取规则 如(-1,3,-1,3,-1 || -1,-1,-1,-3,-1,-1,-1) !!!目前处理必须连续
    function mc_get_param_by_rule(arr_data, str_type) {
        var ui_cnt = arr_data.length;

        // 无虚点数组
        var arr_data_no_v = [];
        // 创建新数组 防止出现虚点
        var arr_new = [];
        // 颜色
        // var str_r = "";

        for (var id = 0; id < ui_cnt; id++) {
            var str_r = arr_data[id].color;

            if ("V" === str_r) {
                continue;
            }
            arr_data_no_v.push(arr_data[id]);
        }

        var ui_ne_cnt = arr_data_no_v.length;

        // 需为偶数
        if (0 !== (ui_ne_cnt % 2)) {
            return [false];
        }

        arr_new = new Array(ui_ne_cnt);
        // 获取需处理的所有x或y
        for (var idx = 0; idx < ui_ne_cnt; idx++) {
            if ("x" === str_type) {
                arr_new[idx] = arr_data_no_v[idx].img_x;
            } else {
                arr_new[idx] = arr_data_no_v[idx].img_y;
            }
        }

        // 总差值数组
        var arr_diff = new Array(ui_ne_cnt - 1);


        // 获取所有差值
        for (var key = 0; key < ui_ne_cnt; key++) {
            if (key === ui_ne_cnt - 1) {
                break;
            }
            var ui_sub = Number(arr_new[key + 1]) - Number(arr_new[key]);

            arr_diff[key] = ui_sub;
        }


        // 根据差值数组 查看是否符合填充规则 并得出规则参数
        // 段数组 (第一段)
        var arr_parp = [arr_diff[0]];
        // 总段数
        var arr_all_parp = [];
        var b_exict_parp1 = true;
        // 其他段
        var other_parp = [];
        // 第一段长度
        var ui_first_parp_cnt = 0;

        for (var keys = 1; keys < arr_diff.length; keys++) {
            var each_diff = arr_diff[keys];

            if (b_exict_parp1) {
                arr_parp.push(each_diff);
                if (each_diff !== arr_parp[0]) {
                    arr_all_parp.push(arr_parp);
                    ui_first_parp_cnt = arr_parp.length;
                    b_exict_parp1 = false;
                }
                continue;
            }

            // 存剩下的每一段
            other_parp.push(each_diff);

            // 一样长度 或 最后一段会缺一个   存储一段
            if (ui_first_parp_cnt === other_parp.length || keys === arr_diff.length - 1) {
                arr_all_parp.push(other_parp);

                other_parp = [];
            }
        }


        // 检测当前总差值数组是否符合段数组规律 所有段跟第一段比
        for (var key_d = 1; key_d < arr_all_parp.length; key_d++) {
            for (var key_f = 0; key_f < ui_first_parp_cnt; key_f++) {
                var fisrt_val = arr_parp[key_f];
                var other_val = arr_all_parp[key_d][key_f];

                // 最后段最后面位置
                if (!other_val) {
                    break;
                    // // 最后一个就跳过
                    // if (key_f === ui_first_parp_cnt - 1 && key_d === arr_all_parp.length - 1) {
                    //     break;
                    // } else {
                    //     // 不是最后一段则
                    //     return [false];
                    // }
                }

                if (fisrt_val !== other_val) {
                    return [false];
                }
            }
        }


        return [true, arr_parp, arr_new];
    }

    // 比较x还是y当前 返回 : /*  par1: 是否同行或同列 par2: 当前要处理的行或列  */
    function mc_get_x_or_y_rule(arr_x, arr_y) {
        // 先清除数组可能有虚点造成出现undefined
        var ui_cnt_x = arr_x.length;
        var ui_cnt_y = arr_y.length;

        var arr_new_x = [];
        var arr_new_y = [];

        for (var id_n = 0; id_n < ui_cnt_x; id_n++) {
            var x_each = arr_x[id_n];

            if ("undefined" === x_each || "number" !== typeof (x_each)) {
                continue;
            }
            arr_new_x.push(arr_x[id_n]);
        }
        for (var key_n = 0; key_n < ui_cnt_y; key_n++) {
            var y_each = arr_y[key_n];

            if ("undefined" === y_each || "number" !== typeof (y_each)) {
                continue;
            }
            arr_new_y.push(arr_y[key_n]);
        }

        var ui_cnt_x_new = arr_new_x.length;
        var ui_cnt_y_new = arr_new_y.length;


        var ui_first_x = arr_new_x[0];
        var ui_first_y = arr_new_y[0];

        var b_is_x = true;
        var b_is_y = true;

        //先比较x

        for (var id_x = 0; id_x < ui_cnt_x_new; id_x++) {
            var each_x = arr_new_x[id_x];


            if (each_x !== ui_first_x) {
                b_is_x = false;
                break;
            }
        }

        for (var id_y = 0; id_y < ui_cnt_y_new; id_y++) {
            var each_y = arr_new_y[id_y];

            if (each_y !== ui_first_y) {
                b_is_y = false;
                break;
            }
        }

        if (!b_is_x && !b_is_y) {
            return [false];
        }

        // x一样
        if (b_is_x) {
            return [true, "y"];
        }
        if (b_is_y) {
            return [true, "x"];
        }

        return [false];
    }


    // 判断有效点  检测当前有效点数量 检验是否存在空点 超过有效点无需继续添点
    function mc_jungle_efficient_point(arr_point) {
        var ui_effi_point_cnt = 0;

        for (var k = 0; k < arr_point.length; k++) {
            if (!arr_point[k]) {
                return false;
            }
            if ("V" !== arr_point[k].color) {
                ui_effi_point_cnt++;
            }
        }
        // 是否有描有效点
        if (2 > ui_effi_point_cnt || ui_effi_point_cnt >= m_ui_scan_len) {
            return false;
        }
        return ui_effi_point_cnt;
    }


    /* ******************* 补点区域 ***************************************************** */


    /* ******************* 补行规则获取 ***************************************************** */
    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *     执行补点命令,由于目前只有一条补点规则,当出现多条时,需要明确使用规则才可执行补点命令
     * 参数:
     *    @param {Promise<Number>} ui_select_str_idx 指定填充数据线
     *    @param {Promise<Function>} fn_callback 执行结束的回调函数
     * 返回：
     *   NA
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_fill_scan(ui_select_str_idx, fn_callback) {
        if ("function" !== typeof fn_callback) {
            return;
        }
        if (!m_b_is_success || 0 >= m_ary_dot_data.length) {
            fn_callback();
            return;
        }
        for (var idx_str = 0; idx_str < m_ary_dot_data.length; idx_str++) {
            var ui_str_idx = idx_str;
            var ary_fill_str_data = m_ary_dot_data[ui_str_idx];

            if (-1 !== ui_select_str_idx) {
                ui_str_idx = ui_select_str_idx - 1;
                ary_fill_str_data = m_ary_dot_data[ui_str_idx];
            }
            if (0 >= ary_fill_str_data.length) {
                continue;
            }
            var ary_fill_result = mc_fill_scan_1(ary_fill_str_data);

            if (!ary_fill_result) {
                continue;
            }
            m_ary_dot_data[ui_str_idx] = ary_fill_result;
            if (-1 !== ui_select_str_idx) {
                break;
            }
        }
        fn_callback();
    }

    /* ******************* 补行区域 ***************************************************** */
    // 此区域存放所有关于补行功能的函数
    // 以下填充情况整套流程只允许使用其中一种,当成功后,将不再执行一下任何一条函数

    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *    补行规则1
     * 参数:
     *     @param {Promise<Array>} ary_str_data 一条线的数据
     * 返回：
     *   @returns {Promise<Array>} 补充结果
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_fill_scan_1(ary_str_data) {
        if (ary_str_data.length >= m_ui_scan_cnt) {
            return ary_str_data;
        }
        var ui_scan_cnt = ary_str_data.length;
        var ary_result = [];
        var ary_rule_grp = [];
        var ui_mod_w = m_ui_mod_w;
        var ui_mod_h = m_ui_mod_h;

        if (!mc_file_scan_dispose_data(ary_str_data, ary_result)) {
            return false;
        }

        var obj_scan_offset = {
            // x偏移
            ui_offset_x: 0,
            // y偏移
            ui_offset_y: 0,
            // 行扫偏移
            ui_offset_scan: 0,
            // 设置总扫数
            ui_scan_max: m_ui_scan_cnt,
            // 规则数组索引
            ui_rule_idx: 1,
            // 对应规则组内的索引值
            ui_rule_pix: 0,
            // 已知扫数
            ui_scan_cnt: ui_scan_cnt,
            // 解析结果标识true代表数据可用
            b_get_success: false,
            ary_rule_data: []
        };

        if (1 === ary_str_data.length) {
            mc_one_scan_fill_one_scan(obj_scan_offset, ary_result);
        } else {
            for (var idx_scan = 1; idx_scan <= ui_scan_cnt; idx_scan++) {
                if (0 !== ui_scan_cnt % idx_scan) {
                    obj_scan_offset.ui_offset_x = 0;
                    obj_scan_offset.ui_offset_y = 0;
                    obj_scan_offset.ui_offset_scan = 0;
                    continue;
                }
                mc_one_scan_fill_multi_scan(obj_scan_offset, ary_result, idx_scan);
                if (obj_scan_offset.b_get_success) {
                    obj_scan_offset.ui_scan_max = Math.ceil(m_ui_scan_cnt / idx_scan);
                    break;
                }
            }
        }
        if (!obj_scan_offset.b_get_success || !obj_scan_offset.ary_rule_data) {
            return false;
        }
        ary_rule_grp = obj_scan_offset.ary_rule_data;
        var ary_offset_x = [];
        var ary_offset_y = [];
        var ary_offset_s = [];
        var ary_offset_c = [];
        var ui_effective_idx = -1;

        for (var idx_rule = 0; idx_rule < ary_rule_grp[0].length; idx_rule++) {
            var str_msg_c = ary_rule_grp[0][idx_rule].color;

            ary_offset_c.push(str_msg_c);
            if ("V" === str_msg_c) {
                ary_offset_x.push(0);
                ary_offset_y.push(0);
                ary_offset_s.push(0);
                continue;
            }
            if (0 > ui_effective_idx) {
                ui_effective_idx = idx_rule;
                ary_offset_x.push(0);
                ary_offset_y.push(0);
                ary_offset_s.push(0);
                continue;
            }
            var ui_offset_x = ary_rule_grp[0][idx_rule].img_x - ary_rule_grp[0][ui_effective_idx].img_x;
            var ui_offset_y = ary_rule_grp[0][idx_rule].img_y - ary_rule_grp[0][ui_effective_idx].img_y;
            var ui_offset_scan = ary_rule_grp[0][idx_rule].scan_idx - ary_rule_grp[0][ui_effective_idx].scan_idx;

            ui_effective_idx = idx_rule;
            ary_offset_x.push(ui_offset_x);
            ary_offset_y.push(ui_offset_y);
            ary_offset_s.push(ui_offset_scan);
        }

        var ui_rule_grp_cnt = ary_rule_grp[0].length;
        var obj_add_scan_pix = new mc_js_map();

        for (var idx_cnt = obj_scan_offset.ui_rule_idx; idx_cnt < obj_scan_offset.ui_scan_max; idx_cnt++) {
            for (var idx_end = obj_scan_offset.ui_rule_pix; idx_end < ui_rule_grp_cnt; idx_end++) {
                // 获取差值数组第I点
                var ui_differ_x = ary_offset_x[idx_end];
                var ui_differ_y = ary_offset_y[idx_end];
                var ui_differ_s = ary_offset_s[idx_end];
                var str_color = ary_offset_c[idx_end];

                // 创建节点
                var ui_add_x = 0;
                var ui_add_y = 0;
                var ui_add_s = m_ui_scan_cnt;
                var str_add_clr = "V";

                // 上一组第i点坐标
                var ui_grp_idx_prev = ary_result.length - ui_rule_grp_cnt;

                // 获取上一组第i点数据
                var ui_prev_grp_x = ary_result[ui_grp_idx_prev].img_x;
                var ui_prev_grp_y = ary_result[ui_grp_idx_prev].img_y;
                var ui_prev_grp_s = ary_result[ui_grp_idx_prev].scan_idx;

                if (0 !== idx_end) {
                    // 取出结果数组最后一个有效点
                    var ui_end_valid_idx = mc_get_end_valid_idx(ary_result);
                    var ui_end_x = ary_result[ui_end_valid_idx].img_x;
                    var ui_end_y = ary_result[ui_end_valid_idx].img_y;
                    var ui_end_s = ary_result[ui_end_valid_idx].scan_idx;
                    // 生成节点数据

                    ui_add_x = (ui_end_x + ui_differ_x + ui_mod_w) % ui_mod_w;
                    ui_add_y = (ui_end_y + ui_differ_y + ui_mod_h) % ui_mod_h;
                    ui_add_s = (ui_end_s + ui_differ_s + m_ui_scan_cnt) % m_ui_scan_cnt;
                } else {
                    // 生成节点数据
                    ui_add_x = (ui_prev_grp_x + obj_scan_offset.ui_offset_x + ui_mod_w) % ui_mod_w;
                    ui_add_y = (ui_prev_grp_y + obj_scan_offset.ui_offset_y + ui_mod_h) % ui_mod_h;
                    ui_add_s = (ui_prev_grp_s + obj_scan_offset.ui_offset_scan + m_ui_scan_cnt) % m_ui_scan_cnt;
                }
                str_add_clr = str_color;

                var obj_add_point = {
                    img_x: ui_add_x,
                    img_y: ui_add_y,
                    color: str_add_clr,
                    scan_idx: ui_add_s
                };

                if ("V" === str_add_clr) {
                    // 存入走点
                    ary_result.push({
                        img_x: 0,
                        img_y: 0,
                        color: "V",
                        scan_idx: ui_add_s
                    });
                    continue;
                }

                // 判断是否存在改坐标
                var str_add_point = obj_add_point.img_x + "_" + obj_add_point.img_y + "_" + str_add_clr;

                while (
                    obj_map_point.get(str_add_point) ||
                    obj_add_scan_pix.get(str_add_point)
                ) {
                    if (
                        !mc_scan_updata_offset(obj_add_point, obj_scan_offset)
                    ) {
                        return false;
                    }
                    str_add_point = obj_add_point.img_x + "_" + obj_add_point.img_y + "_" + str_add_clr;
                }
                obj_add_scan_pix.set(str_add_point, 1);
                // 存入走点
                ary_result.push(obj_add_point);
            }
            obj_scan_offset.ui_rule_idx++;
            obj_scan_offset.ui_rule_pix = 0;
        }

        var ary_return = mc_get_log_ary_by_end(ary_result);

        // 解析结束后
        return ary_return;
    }
    // 行扫出现重复点更新偏移,根据已知偏移信息由非0偏移决定更新偏移值,由更新偏移值的正负决定更新偏移的新偏移量 正则 + 1 负则-1
    function mc_scan_updata_offset(obj_add_point, obj_scan_offset) {
        var ui_offset_x = obj_scan_offset.ui_offset_x;
        var ui_offset_y = obj_scan_offset.ui_offset_y;

        if (
            0 === ui_offset_x &&
            0 === ui_offset_y
        ) {
            return false;
        }
        if (0 === ui_offset_x) {
            if (0 > ui_offset_y) {
                obj_add_point.img_y -= 1;
            } else {
                obj_add_point.img_y += 1;
            }
        } else {
            if (0 > ui_offset_x) {
                obj_add_point.img_x -= 1;
            } else {
                obj_add_point.img_x += 1;
            }
        }
        if (
            0 > obj_add_point.img_x ||
            obj_add_point.img_x >= m_ui_mod_w ||
            0 > obj_add_point.img_y ||
            obj_add_point.img_y >= m_ui_mod_h
        ) {
            return false;
        }
        return true;
    }

    // 为补行解析数据,并判断数据可用性
    function mc_file_scan_dispose_data(ary_str_data, ary_result) {
        for (var idx_end_scan = 0; idx_end_scan < ary_str_data.length; idx_end_scan++) {
            if (0 !== idx_end_scan && ary_str_data[idx_end_scan].length !== ary_str_data[idx_end_scan - 1].length) {
                return false;
            }
            var ui_scan_pix = 0;

            for (var idx_scan_pix = 0; idx_scan_pix < ary_str_data[idx_end_scan].length; idx_scan_pix++) {
                var obj_point = ary_str_data[idx_end_scan][idx_scan_pix];

                if (!obj_point) {
                    return false;
                }
                var obj_pix = {
                    img_x: obj_point.img_x,
                    img_y: obj_point.img_y,
                    color: obj_point.color,
                    scan_idx: idx_end_scan
                };

                if ("V" !== obj_pix.color) {
                    ui_scan_pix++;
                }

                ary_result.push(obj_pix);
            }
            if (ui_scan_pix !== m_ui_scan_len) {
                return false;
            }
        }
        return true;
    }
    // 解析结果数组,获取内存数组
    function mc_get_log_ary_by_end(ary_end) {
        var ary_str = [];
        var ui_scan_current = -1;

        for (var idx_str = 0; idx_str < ary_end.length; idx_str++) {
            var ui_scan_idx = ary_end[idx_str].scan_idx;
            var ui_x = ary_end[idx_str].img_x;
            var ui_y = ary_end[idx_str].img_y;
            var str_clr = ary_end[idx_str].color;

            if ("V" !== str_clr) {
                var str_add_point = ui_x + "_" + ui_y + "_" + str_clr;

                obj_map_point.set(str_add_point, 1);
            }

            if (ui_scan_idx !== ui_scan_current) {
                ui_scan_current = ui_scan_idx;
                ary_str.push([]);
            }
            ary_str[ui_scan_current].push(ary_end[idx_str]);
        }
        if (ary_str.length !== m_ui_scan_cnt) {
            return false;
        }
        return ary_str;
    }
    // 获取结果数组最后一个有效点下标
    function mc_get_end_valid_idx(ary_end) {
        if (0 >= ary_end.length) {
            return false;
        }
        for (var idx_end = ary_end.length - 1; 0 < idx_end; idx_end--) {
            var str_color = ary_end[idx_end].color;

            if ("V" !== str_color) {
                return idx_end;
            }
        }
        return false;
    }

    // 当只有一扫时
    function mc_one_scan_fill_one_scan(obj_scan_offset, ary_result) {
        var ary_point_edge_loc = mc_get_point_edge_loc(ary_result);

        // 解析逻辑: 将符合规律的点分为段 将符合规律的段分为块 将符合规律的快分为组
        obj_scan_offset.ary_rule_data = [ary_result];

        obj_scan_offset.ui_offset_scan = 1;
        obj_scan_offset.ui_scan_max = m_ui_scan_cnt;
        obj_scan_offset.ui_rule_pix = 0;
        obj_scan_offset.ui_rule_idx = 1;

        mc_get_offset_by_direction(ary_point_edge_loc, obj_scan_offset, ary_result);
    }
    // 获取已知走点最大最小X,Y坐标
    function mc_get_point_edge_loc(ary_point_data) {
        var ui_max_x = -1;
        var ui_max_y = -1;
        var ui_min_x = -1;
        var ui_min_y = -1;

        for (var idx_point = 0; idx_point < ary_point_data.length; idx_point++) {
            var obj_point = ary_point_data[idx_point];
            var ui_img_x = obj_point.img_x;
            var ui_img_y = obj_point.img_y;
            var str_clr = obj_point.color;

            if ("V" === str_clr) {
                continue;
            }
            if (-1 === ui_max_x) {
                ui_max_x = ui_img_x;
                ui_max_y = ui_img_y;
                ui_min_x = ui_img_x;
                ui_min_y = ui_img_y;
                continue;
            }
            if (ui_max_x < ui_img_x) {
                ui_max_x = ui_img_x;
            }
            if (ui_max_y < ui_img_y) {
                ui_max_y = ui_img_y;
            }
            if (ui_min_x > ui_img_x) {
                ui_min_x = ui_img_x;
            }
            if (ui_min_y > ui_img_y) {
                ui_min_y = ui_img_y;
            }
        }
        return [ui_max_x, ui_max_y, ui_min_x, ui_min_y];
    }

    // 根据方向获取单扫偏移值
    function mc_get_offset_by_direction(ary_point_edge_loc, obj_scan_offset, ary_result) {
        // 当前走点偏移方向 1为正方形 -1为负方向
        var ui_offset_direction = 0;
        // 偏移类型 1为 X轴 -1为Y轴
        var ui_offset_type = 0;
        // 创建一个边界数组 检测标准下的边界
        var ary_bound = [];

        obj_scan_offset.b_get_success = true;

        var obj_offset_msg = mc_get_offset_direction(ary_point_edge_loc);

        if (!obj_offset_msg) {
            obj_scan_offset.b_get_success = false;
            return;
        }

        ary_bound = obj_offset_msg.bound;
        ui_offset_direction = obj_offset_msg.offset_dec;
        ui_offset_type = obj_offset_msg.offset_type;

        var ui_first_rule_val = 0 < ui_offset_type ? ary_result[0].img_x : ary_result[0].img_y;
        // 根据偏移类型 获取偏移坐标下左右有效点

        for (var idx_rule = 0; idx_rule < ary_result.length; idx_rule++) {
            var obj_point = ary_result[idx_rule];
            var ui_rule_value = -1;

            if ("V" === obj_point.color) {
                continue;
            }

            if (0 < ui_offset_type) {
                ui_rule_value = obj_point.img_x;
            } else {
                ui_rule_value = obj_point.img_y;
            }
            ary_bound[ui_rule_value] = 1;
        }
        // 获取偏移间距
        var ui_offset_direcvtion = -1;
        // 偏移标准宽度 (为第一段)
        var ui_offset_val = -1;
        // 用来计算最大宽度的指针
        var ui_pointer_width_1 = -1;
        var ui_pointer_width_2 = 0;

        // 指针 记录上一个坐标
        var ui_pointer = 0;

        // 悬停状态(当出现有效坐标时 悬停记录指针)
        var b_is_stop = false;

        // 当前悬停区域宽度
        var ui_strop_width = 0;

        //当前悬停区域宽度为标准宽度
        var b_is_offset_val = false;


        for (var idx_offset = 0; idx_offset < ary_bound.length; idx_offset++) {
            var ui_state = ary_bound[idx_offset];

            if (idx_offset === ui_first_rule_val) {
                b_is_offset_val = true;
            }
            if (1 === ui_state) {
                var ui_last_idx = ui_pointer;
                // 只有非悬停状态才记录

                if (!b_is_stop) {
                    ui_pointer = idx_offset;
                    // 获取偏移标准宽度
                }
                ui_strop_width = idx_offset - ui_pointer;
                // 记录开头有效位置
                if (-1 === ui_pointer_width_1) {
                    ui_pointer_width_1 = idx_offset;
                }

                if (b_is_offset_val) {
                    // 根据偏移方向 区分
                    if (0 < ui_offset_direction) {
                        // 正方向
                        // 获取偏移间距
                        if (-1 !== ui_offset_val) {
                            ui_offset_direcvtion = idx_offset - ui_last_idx;
                        }
                    }
                    ui_offset_val = ui_strop_width + 1;
                    if (0 > ui_offset_direction) {
                        // 负方向
                        // 获取偏移间距
                        if (-1 !== ui_offset_val) {
                            ui_offset_direcvtion = idx_offset - ui_last_idx;
                        }
                    }
                }


                // 记录结尾有效位置
                ui_pointer_width_2 = idx_offset;


                b_is_stop = true;
            } else {
                if (b_is_stop) {
                    ui_pointer = idx_offset - 1;
                }
                b_is_stop = false;
                if (b_is_offset_val) {
                    b_is_offset_val = false;
                }
            }
        }
        if (-1 === ui_offset_direcvtion) {
            ui_offset_direcvtion = ary_bound.length - (ui_pointer_width_2 + 1);
        }

        // 计算偏移信息并存入对象
        mc_set_offset_msg(ui_offset_direcvtion, ui_offset_val, ui_offset_type, ui_offset_direction, ui_pointer_width_1, ui_pointer_width_2, obj_scan_offset);
    }

    // 计算偏移信息并存入对象
    function mc_set_offset_msg(ui_offset_direcvtion, ui_offset_val, ui_offset_type, ui_offset_direction, ui_pointer_width_1, ui_pointer_width_2, obj_scan_offset) {
        if (ui_offset_direcvtion >= ui_offset_val * (m_ui_scan_cnt - 1)) {
            if (0 < ui_offset_type) {
                obj_scan_offset.ui_offset_x = ui_offset_val * ui_offset_direction;
                obj_scan_offset.ui_offset_y = 0;
            } else {
                obj_scan_offset.ui_offset_x = 0;
                obj_scan_offset.ui_offset_y = ui_offset_val * ui_offset_direction;
            }
        } else {
            var ui_max_width = ui_pointer_width_2 - ui_pointer_width_1 + 1;

            if (0 < ui_offset_type) {
                obj_scan_offset.ui_offset_x = ui_max_width * ui_offset_direction;
                obj_scan_offset.ui_offset_y = 0;
            } else {
                obj_scan_offset.ui_offset_x = 0;
                obj_scan_offset.ui_offset_y = ui_max_width * ui_offset_direction;
            }
        }
    }
    // 获取偏移方向
    function mc_get_offset_direction(ary_point_edge_loc) {
        var obj_retunr = {
            bound: [],
            offset_dec: -1,
            offset_type: -1
        };
        // 已知走点的最对小x y
        var ui_max_x = ary_point_edge_loc[0];
        var ui_max_y = ary_point_edge_loc[1];
        var ui_min_x = ary_point_edge_loc[2];
        var ui_min_y = ary_point_edge_loc[3];
        // 已知走点区域相对于边界的距离
        var ui_distance_mod_left = ui_min_x - 0;
        var ui_distance_mod_right = (m_ui_mod_w - 1) - ui_max_x;
        var ui_distance_mod_top = ui_min_y - 0;
        var ui_distance_mod_bottom = (m_ui_mod_h - 1) - ui_max_y;

        if (
            ui_distance_mod_left === ui_distance_mod_right &&
            ui_distance_mod_left === ui_distance_mod_top &&
            ui_distance_mod_left === ui_distance_mod_bottom
        ) {
            return false;
        } else if (
            ui_distance_mod_left >= ui_distance_mod_right &&
            ui_distance_mod_left >= ui_distance_mod_top &&
            ui_distance_mod_left >= ui_distance_mod_bottom
        ) {
            obj_retunr.offset_dec = -1;
            obj_retunr.bound.length = m_ui_mod_w;
            obj_retunr.offset_type = 1;
        } else if (
            ui_distance_mod_right > ui_distance_mod_left &&
            ui_distance_mod_right >= ui_distance_mod_top &&
            ui_distance_mod_right >= ui_distance_mod_bottom
        ) {
            obj_retunr.offset_dec = 1;
            obj_retunr.bound.length = m_ui_mod_w;
            obj_retunr.offset_type = 1;
        } else if (
            ui_distance_mod_top > ui_distance_mod_bottom &&
            ui_distance_mod_top >= ui_distance_mod_left &&
            ui_distance_mod_top >= ui_distance_mod_right
        ) {
            obj_retunr.offset_dec = -1;
            obj_retunr.bound.length = m_ui_mod_h;
            obj_retunr.offset_type = -1;
        } else if (
            ui_distance_mod_bottom >= ui_distance_mod_top &&
            ui_distance_mod_bottom >= ui_distance_mod_left &&
            ui_distance_mod_bottom >= ui_distance_mod_right
        ) {
            obj_retunr.offset_dec = 1;
            obj_retunr.bound.length = m_ui_mod_h;
            obj_retunr.offset_type = -1;
        } else {
            return false;
        }

        return obj_retunr;
    }

    // 多扫数据情况下
    function mc_one_scan_fill_multi_scan(obj_scan_offset, ary_fill_data, ui_grp_idx) {
        var ary_rule_grp = [];
        var ary_rule_data = [];
        var ui_scan_state = -1;
        var ui_offset_x = 0;
        var ui_offset_y = 0;
        var ui_offset_scan = 0;
        var ui_grp_pix = 0;

        for (var idx_scan = 0; idx_scan < ary_fill_data.length; idx_scan++) {
            var ui_scan_idx = ary_fill_data[idx_scan].scan_idx;

            if (0 <= ui_scan_state && ui_scan_state !== ui_scan_idx && 0 === ui_scan_idx % ui_grp_idx) {
                ary_rule_grp.push(ary_rule_data);
                ary_rule_data = [];
            }
            ui_scan_state = ui_scan_idx;
            ary_rule_data.push(ary_fill_data[idx_scan]);
        }
        ary_rule_grp.push(ary_rule_data);

        for (var idx_grp = 1; idx_grp < ary_rule_grp.length; idx_grp++) {
            var ary_grp = ary_rule_grp[idx_grp];
            var ary_grp_prev = ary_rule_grp[idx_grp - 1];
            var ui_grp_cnt = ary_grp.length;

            if (!(idx_grp + 1) !== ary_rule_grp.length) {
                var ui_grp_prev = ary_grp_prev.length;

                if (ui_grp_cnt !== ui_grp_prev) {
                    obj_scan_offset.ui_offset_x = 0;
                    obj_scan_offset.ui_offset_y = 0;
                    return;
                }
            }

            for (ui_grp_pix = 0; ui_grp_pix < ui_grp_cnt; ui_grp_pix++) {
                var str_clr = ary_grp[ui_grp_pix].color;
                var str_clr_prev = ary_grp_prev[ui_grp_pix].color;

                if (str_clr !== str_clr_prev) {
                    obj_scan_offset.ui_offset_x = 0;
                    obj_scan_offset.ui_offset_y = 0;
                    obj_scan_offset.ui_offset_scan = 0;
                    return;
                }
                if ("V" === str_clr) {
                    continue;
                }
                ui_offset_x = ary_grp[ui_grp_pix].img_x - ary_grp_prev[ui_grp_pix].img_x;
                ui_offset_y = ary_grp[ui_grp_pix].img_y - ary_grp_prev[ui_grp_pix].img_y;
                ui_offset_scan = ary_grp[ui_grp_pix].scan_idx - ary_grp_prev[ui_grp_pix].scan_idx;

                if (0 === obj_scan_offset.ui_offset_x && 0 === obj_scan_offset.ui_offset_y && 0 === obj_scan_offset.ui_offset_scan) {
                    obj_scan_offset.ui_offset_x = ui_offset_x;
                    obj_scan_offset.ui_offset_y = ui_offset_y;
                    obj_scan_offset.ui_offset_scan = ui_offset_scan;
                    continue;
                }
                if (ui_offset_x === obj_scan_offset.ui_offset_x && ui_offset_y === obj_scan_offset.ui_offset_y && ui_offset_scan === obj_scan_offset.ui_offset_scan) {
                    continue;
                }
                obj_scan_offset.ui_offset_x = 0;
                obj_scan_offset.ui_offset_y = 0;
                obj_scan_offset.ui_offset_scan = 0;
                return;
            }
        }
        obj_scan_offset.ui_rule_pix = ui_grp_pix;
        obj_scan_offset.ui_rule_idx = ary_rule_grp.length - 1;
        obj_scan_offset.ary_rule_data = ary_rule_grp;
        obj_scan_offset.b_get_success = true;
    }

    /* ******************* 补组规则获取 ***************************************************** */
    function mc_fill_grop(fn_callback) {
        if ("function" !== typeof fn_callback) {
            return;
        }
        var ary_test_data = m_ary_dot_data.concat();

        ary_test_data = mc_supply_group(ary_test_data);
        if (!ary_test_data) {
            m_b_fill_ok = false;
            fn_callback();
            return;
        }
        m_ary_dot_data = ary_test_data;
        fn_callback();
    }

    /* ******************* 补组区域 ********************************************************* */

    /************************************************************************************************
     * 类型:
     *    内部函数
     * 功能:
     *     补组
     * 参数:
     *    @param {Promise<Array>} date 当前一组的所有点数据
     * 返回：
     *   @param {Promise<boolean>} false 补点失败
     *   @param {Promise<Array>} arr_E 成功补组后的数据
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 李智明
     *      时间 : 2021.3.1
     *      内容 : 所有代码
     ************************************************************************************************/

    function mc_supply_group(date) {   // eslint-disable-line
        // 判断此时的点是否等于有效数
        if (!mc_detection_input(date)) {
            return false;
        }

        var arr_exist_point_D = date;
        var arr_E = [];
        var arr_scan_As = [];
        var str_point = "";
        var Gp_idx = 0;

        // 偏移差
        var ui_offset_O = 0;
        var ui_offset_F = 0;
        // 行扫结果数组
        var arr_result_As = [];

        // 循环次数 5次
        var b_next_times = false;
        var ui_get_rule_cnt = 5;


        arr_E = arr_exist_point_D.concat();
        // 设置索引Gi
        for (var Gi_idx = m_ui_grp_mod; Gi_idx < arr_exist_point_D.length; Gi_idx++) {
            // 判断Gi点数
            if (mc_get_Gi_point(arr_exist_point_D[Gi_idx])) {
                continue;
            }
            // 获取上一组GP的点数 m_ui_grp_mod m_ary_str_color.length
            Gp_idx = Gi_idx - m_ui_grp_mod;

            //  上一条线的扫数是否等于 m_ui_scan_cnt
            if (arr_exist_point_D[Gp_idx].length !== m_ui_scan_cnt) {
                return false;
            }

            // 是否对齐
            // for (var Gp_scan_idx = 1; Gp_scan_idx < arr_exist_point_D[Gp_idx].length; Gp_scan_idx++) {
            //     if (arr_exist_point_D[Gp_idx][Gp_scan_idx - 1].length !== arr_exist_point_D[Gp_idx][Gp_scan_idx].length) {
            //         return false;
            //     }
            // }

            if (0 !== ui_offset_O && 0 !== ui_offset_F) {
                ui_get_rule_cnt = 1;
                // 解析Gp点数
            }
            for (var idx_offset = 0; idx_offset < ui_get_rule_cnt; idx_offset++) {
                // 获取O和F值
                if (0 === ui_offset_O && 0 === ui_offset_F) {
                    var arr_O_F_data = mc_get_Gp_point(arr_exist_point_D[Gp_idx], idx_offset, m_ui_grp_cnt);

                    ui_offset_O = arr_O_F_data[0];
                    ui_offset_F = arr_O_F_data[1];

                    if (0 === ui_offset_F || 0 === ui_offset_O) {
                        return false;
                    }
                }

                for (var scan_idx = 0; scan_idx < arr_exist_point_D[Gp_idx].length; scan_idx++) {
                    for (var ui_point = 0; ui_point < arr_exist_point_D[Gp_idx][scan_idx].length; ui_point++) {
                        // 获取上组当前si扫数据
                        var Xn = 0;
                        var Yn = 0;
                        var Cn = "V";
                        var obj_point = {
                            img_x: "",
                            img_y: "",
                            color: "",
                            scan: ""
                        };
                        var point_P = {};
                        var Pi_x = 0;
                        var Pi_y = 0;
                        var Pi_c = "V";

                        point_P = arr_exist_point_D[Gp_idx][scan_idx][ui_point];
                        Pi_x = point_P.img_x;
                        Pi_y = point_P.img_y;
                        Pi_c = point_P.color;
                        if ("V" === Pi_c) {
                            obj_point.img_x = Xn;
                            obj_point.img_y = Yn;
                            obj_point.color = Cn;
                            obj_point.scan = scan_idx;
                        } else {
                            if (0 > ui_offset_F) {
                                Xn = (Pi_x + ui_offset_O + Number(m_ui_mod_w)) % Number(m_ui_mod_w);
                                Yn = Pi_y;
                            } else {
                                Xn = Pi_x;
                                Yn = (Pi_y + ui_offset_O + Number(m_ui_mod_h)) % Number(m_ui_mod_h);
                            }
                            Cn = Pi_c;

                            // 判断是否存在
                            str_point = Xn + "_" + Yn + "_" + Cn;

                            if (obj_map_point.get(str_point)) {
                                if (4 === idx_offset) {
                                    return false;
                                }
                                b_next_times = true;
                                break;
                            }
                            obj_point.img_x = Xn;
                            obj_point.img_y = Yn;
                            obj_point.color = Cn;
                            obj_point.scan = scan_idx;
                        }

                        arr_result_As.push(obj_point);
                    }
                    if (b_next_times) {
                        arr_exist_point_D = arr_E.concat();
                        arr_result_As = [];
                        arr_scan_As = [];
                        break;
                    } else {
                        arr_scan_As.push(arr_result_As);
                        arr_result_As = [];
                    }
                }
                if (b_next_times) {
                    b_next_times = false;
                    ui_offset_O = 0;
                    ui_offset_F = 0;
                } else {
                    arr_exist_point_D[Gi_idx] = arr_scan_As;
                    arr_scan_As = [];
                    ui_get_rule_cnt = 1;
                }
            }
        }


        if (mc_jungle_grp_result(arr_exist_point_D)) {
            arr_E = arr_exist_point_D;
            return arr_E;
        }
        return false;
    }

    // 处理初入补组的数据 , m_ui_scan_len, m_ary_str_color
    function mc_detection_input(date) {
        var ui_vaild_pit = 0;

        for (var idx_jungle_grp = 0; idx_jungle_grp < date.length; idx_jungle_grp++) {
            for (var idx_jungle_line = 0; idx_jungle_line < date[idx_jungle_grp].length; idx_jungle_line++) {
                for (var idx_jungle_pnt = 0; idx_jungle_pnt < date[idx_jungle_grp][idx_jungle_line].length; idx_jungle_pnt++) {
                    if (!date[idx_jungle_grp][idx_jungle_line][idx_jungle_pnt]) {
                        return false;
                    }
                    if ("V" !== date[idx_jungle_grp][idx_jungle_line][idx_jungle_pnt].color) {
                        ui_vaild_pit++;
                    }
                }
                if (ui_vaild_pit !== m_ui_scan_len) {
                    return false;
                }
                ui_vaild_pit = 0;
            }

            if (idx_jungle_grp === m_ary_str_color.length) {
                break;
            }
        }
        return true;
    }

    // 验证最终补组结果是否规范 长度
    function mc_jungle_grp_result(arr) {
        for (var idx_result_grp = 1; idx_result_grp < arr.length; idx_result_grp++) {
            if (arr[idx_result_grp].length !== arr[idx_result_grp - 1].length) {
                return false;
            }
            for (var idx_result_scan = 1; idx_result_scan < arr[idx_result_grp].length; idx_result_scan++) {
                if (arr[idx_result_grp][idx_result_scan].length !== arr[idx_result_grp][idx_result_scan - 1].length) {
                    return false;
                }
            }
        }
        return true;
    }


    // 解析Gi点数
    function mc_get_Gi_point(data) {
        var Gi_date = data;
        // 获取Gi线的点

        if (0 === Gi_date.length) {
            return false;
        }

        for (var Gi_scan_idx = 0; Gi_scan_idx < Gi_date.length; Gi_scan_idx++) {
            if (0 < Gi_date[Gi_scan_idx].length) {
                return true;
            }
        }
        return false;
    }


    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    获取O和F值
     * 参数:
     *    @param {promises<Array>} data 数据
     *    @param {promises<Number>} idx_offset 数值
     * 返回：
     *   @returns {Promise<Array>} 数组
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 李智明
     *      时间 : 2020.10.13
     *      内容 : 所有代码
     ************************************************************************************************/
    // , m_ui_grp_cnt
    function mc_get_Gp_point(data, idx_offset) {
        var Gp_date = data;
        var ui_return_O;
        var ui_return_F;
        // var ui_grp_cnt = m_ui_grp_cnt;

        var XL;
        var XR;
        var YT;
        var YB;
        // xy最大最小值
        var ui_max_X = 0;
        var ui_min_X = 0;
        var ui_max_Y = 0;
        var ui_min_Y = 0;

        var b_get_val = true;

        var arr_critical_x_y = mc_get_min_max_x_y(Gp_date);

        ui_max_X = arr_critical_x_y[0];
        ui_min_X = arr_critical_x_y[1];
        ui_max_Y = arr_critical_x_y[2];
        ui_min_Y = arr_critical_x_y[3];

        // 求最大值xy
        function mc_get_min_max_x_y(arr) {
            var max_x;
            var min_x;
            var max_y;
            var min_y;

            // 求出xy坐标
            for (var all_scan_idx = 0; all_scan_idx < arr.length; all_scan_idx++) {
                for (var all_point_idx = 0; all_point_idx < arr[all_scan_idx].length; all_point_idx++) {
                    if ("V" !== arr[all_scan_idx][all_point_idx].color) {
                        if (b_get_val) {
                            max_x = arr[all_scan_idx][all_point_idx].img_x;
                            min_x = arr[all_scan_idx][all_point_idx].img_x;
                            max_y = arr[all_scan_idx][all_point_idx].img_y;
                            min_y = arr[all_scan_idx][all_point_idx].img_y;
                            b_get_val = false;
                        }

                        if (max_x < arr[all_scan_idx][all_point_idx].img_x) {
                            max_x = arr[all_scan_idx][all_point_idx].img_x;
                        }
                        if (min_x > arr[all_scan_idx][all_point_idx].img_x) {
                            min_x = arr[all_scan_idx][all_point_idx].img_x;
                        }
                        if (max_y < arr[all_scan_idx][all_point_idx].img_y) {
                            max_y = arr[all_scan_idx][all_point_idx].img_y;
                        }
                        if (min_y > arr[all_scan_idx][all_point_idx].img_y) {
                            min_y = arr[all_scan_idx][all_point_idx].img_y;
                        }
                    }
                }
            }
            return [max_x, min_x, max_y, min_y];
        }

        if (4 > idx_offset) {
            XL = ui_min_X;
            XR = m_ui_mod_w - ui_max_X;
            YT = ui_min_Y;
            YB = m_ui_mod_h - ui_max_Y;

            if (XL >= XR && XL >= YT && XL >= YB) {
                return [-1, -1];
            } else if (XR >= XL && XR >= YT && XR >= YB) {
                return [1, -1];
            } else if (YT >= XL && YT >= XR && YT >= YB) {
                return [-1, 1];
            } else if (YB >= XL && YB >= YT && YB >= XR) {
                return [1, 1];
            }
        } else {
            ui_return_F = mc_get_offset_direction([ui_max_X, ui_max_Y, ui_min_X, ui_min_Y]);
            if (!ui_return_F) {
                return [0, 0];
            }
            ui_return_F = -ui_return_F.offset_type;
            // ui_grp_cnt
            ui_return_O = mc_get_O(ui_return_F, Gp_date);

            return [ui_return_O, ui_return_F];
        }
        return [0, 0];
    }

    //求O
    function mc_get_O(ui_return_F, Gp_date) {
        var ui_F = ui_return_F;
        var arr_data = Gp_date;
        // var ui_grp_all_cnt = ui_grp_cnt;
        // 记录规则数组
        // var arr_rule = [];
        var new_arr = [];

        var arr_rule = mc_get_date(ui_F, arr_data);

        function mc_get_date(F_id, arr) {
            //记录临时的存储
            var arr_temp = [];
            var arr_temp_data = [];

            if (0 > F_id) {
                arr_temp.push(arr[0][0].img_x);
                arr_temp_data.length = m_ui_mod_w;
                arr_temp_data[arr[0][0].img_x] = true;
                for (var idx_grp = 0; idx_grp < arr.length; idx_grp++) {
                    for (var idx_point = 0; idx_point < arr[idx_grp].length; idx_point++) {
                        if (-1 === arr_temp.indexOf(arr[idx_grp][idx_point].img_x) && "V" !== arr[idx_grp][idx_point].color) {
                            arr_temp_data[arr[idx_grp][idx_point].img_x] = true;
                            arr_temp.push(arr[idx_grp][idx_point].img_x);
                        }
                    }
                }
            } else {
                arr_temp.push(arr[0][0].img_y);
                arr_temp_data.length = m_ui_mod_h;
                arr_temp_data[arr[0][0].img_y] = true;
                for (var idx_grp_w = 0; idx_grp_w < arr.length; idx_grp_w++) {
                    for (var idx_point_w = 0; idx_point_w < arr[idx_grp_w].length; idx_point_w++) {
                        if (-1 === arr_temp.indexOf(arr[idx_grp_w][idx_point_w].img_y) && "V" !== arr[idx_grp_w][idx_point_w].color) {
                            arr_temp_data[arr[idx_grp_w][idx_point_w].img_y] = true;
                            arr_temp.push(arr[idx_grp_w][idx_point_w].img_y);
                        }
                    }
                }
            }
            return arr_temp_data;
        }

        for (var idx_result = 0; idx_result < arr_rule.length; idx_result++) {
            if (arr_rule[idx_result]) {
                new_arr.push(idx_result);
            }
        }

        // 解析最新数组数据 求差值 如 0189
        // 组偏差值 7
        var ui_diff_offset_val;
        // 第一组数量 2
        var ui_diff_val;
        // 偏差值的右边第一个值 8
        // var ui_next_grp;
        // 最后一个值 9
        var ui_last_val = new_arr[new_arr.length - 1];

        for (var idx_diff = 2; idx_diff < new_arr.length; idx_diff++) {
            if (new_arr[idx_diff] - new_arr[idx_diff - 1] !== new_arr[idx_diff - 1] - new_arr[idx_diff - 2]) {
                ui_diff_offset_val = new_arr[idx_diff] - new_arr[idx_diff - 1];
                ui_diff_val = idx_diff;
                // ui_next_grp = new_arr[idx_diff];
                break;
            }
        }


        // if (ui_diff_val * (ui_grp_all_cnt - 1) === ui_next_grp - ui_diff_val) {

        // 左右补
        if (0 > ui_F) {
            if (m_ui_mod_w - ui_last_val >= ui_diff_offset_val) {
                return ui_diff_val;
            } else if (m_ui_mod_w - new_arr[0] >= ui_diff_offset_val) {
                return -ui_diff_val;
            }
            // 此判断 防止完整一组数据得不出O 完整一组则偏移为一组长度
            if (!ui_diff_offset_val) {
                //右 左 宽
                if (m_ui_mod_w - (new_arr[new_arr.length - 1] + 1) >= m_ui_mod_w - (new_arr[new_arr.length - 1] - new_arr[0]) - (m_ui_mod_w - new_arr[new_arr.length - 1])) {
                    return new_arr.length;
                }
                return -new_arr.length;
            }
            return ui_last_val + 1;
        }
        // 上下补
        if (m_ui_mod_h - ui_last_val >= ui_diff_offset_val) {
            return ui_diff_val;
        } else if (m_ui_mod_h - new_arr[0] >= ui_diff_offset_val) {
            return -ui_diff_val;
        }
        // 此判断 防止完整一组数据得不出O 完整一组则偏移为一组长度
        if (!ui_diff_offset_val) {
            // 上 下 高
            if (m_ui_mod_h - (new_arr[new_arr.length - 1] + 1) >= m_ui_mod_h - (new_arr[new_arr.length - 1] - new_arr[0]) - (m_ui_mod_h - new_arr[new_arr.length - 1])) {
                return new_arr.length;
            }
            return -new_arr.length;
        }
        return ui_last_val + 1;
        // }
        // return ui_last_val + 1;
    }

    /* ******************* 通用函数存放区域 ***************************************************** */
    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    按规律的段区分为各组
     * 参数:
     *    @param {promises<Array>} ary_segment 已经获取到的段规则数据
     * 返回：
     *   @returns {Promise<Array>} 数组
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_get_ary_chunk(ary_segment) {
        if (0 >= ary_segment.length) {
            return false;
        }
        var ary_rule_chunk = [];
        var ui_offset_x = 0;
        var ui_offset_y = 0;
        var ui_segment_cnt = ary_segment.length;
        var obj_req_data = {};

        for (var idx_rule = 1; idx_rule < (ui_segment_cnt); idx_rule++) {
            if (0 !== ui_segment_cnt % idx_rule) {
                ui_offset_x = 0;
                ui_offset_y = 0;
                continue;
            }
            ary_rule_chunk = [];
            var ary_chunk_val = [];

            for (var idx_chunk = 0; idx_chunk < ui_segment_cnt; idx_chunk++) {
                if (ary_chunk_val.length === idx_rule) {
                    ary_rule_chunk.push(ary_chunk_val);
                    ary_chunk_val = [];
                }
                ary_chunk_val.push(ary_segment[idx_chunk]);
            }
            ary_rule_chunk.push(ary_chunk_val);
            var ary_test_grp = mc_get_test_grop_data(ary_rule_chunk);
            var idx_grp = 0;

            for (idx_grp = 1; idx_grp < ary_test_grp.length; idx_grp++) {
                var ary_grp = ary_test_grp[idx_grp];
                var ary_grp_prev = ary_test_grp[idx_grp - 1];

                if (!(idx_grp + 1) === ary_test_grp.length) {
                    var ui_grp_cnt = ary_grp.length;
                    var ui_grp_cnt_prev = ary_grp_prev.length;

                    if (ui_grp_cnt !== ui_grp_cnt_prev) {
                        break;
                    }
                }
                var idx_val = 0;

                for (idx_val = 0; idx_val < ary_grp.length; idx_val++) {
                    if (!ary_grp_prev[idx_val]) {
                        break;
                    }
                    var ui_img_x = ary_grp[idx_val].img_x;
                    var ui_img_x_prev = ary_grp_prev[idx_val].img_x;
                    var ui_img_y = ary_grp[idx_val].img_y;
                    var ui_img_y_prev = ary_grp_prev[idx_val].img_y;
                    var ui_img_c = ary_grp[idx_val].color;
                    var ui_img_c_prev = ary_grp_prev[idx_val].color;

                    if (ui_img_c !== ui_img_c_prev) {
                        break;
                    }
                    if ("V" === ui_img_c) {
                        continue;
                    }
                    var ui_offset_x_each = ui_img_x - ui_img_x_prev;
                    var ui_offset_y_each = ui_img_y - ui_img_y_prev;

                    if (0 === ui_offset_x && 0 === ui_offset_y) {
                        ui_offset_x = ui_offset_x_each;
                        ui_offset_y = ui_offset_y_each;
                    }
                    if (ui_offset_x !== ui_offset_x_each || ui_offset_y !== ui_offset_y_each) {
                        break;
                    }
                }
                if (idx_val < ary_grp.length) {
                    break;
                }
            }
            if (idx_grp < ary_test_grp.length) {
                ui_offset_x = 0;
                ui_offset_y = 0;
                continue;
            }
            obj_req_data = {
                ui_offset_x: ui_offset_x,
                ui_offset_y: ui_offset_y,
                ary_segment_grp: ary_rule_chunk
            };

            return obj_req_data;
        }
        obj_req_data = {
            ui_offset_x: 0,
            ui_offset_y: 0,
            ary_segment_grp: ary_segment
        };

        return obj_req_data;
    }
    // 解析已知块规则区域,生成测试数据
    function mc_get_test_grop_data(ary_rule_chunk) {
        if (0 >= ary_rule_chunk.length) {
            return [];
        }
        var ary_test_val = [];

        for (var idx_chunk = 0; idx_chunk < ary_rule_chunk.length; idx_chunk++) {
            ary_test_val.push([]);
            var ary_segment = ary_rule_chunk[idx_chunk];

            for (var idx_segment = 0; idx_segment < ary_segment.length; idx_segment++) {
                var ary_segment_val = ary_segment[idx_segment];

                for (var idx_pix = 0; idx_pix < ary_segment_val.length; idx_pix++) {
                    ary_test_val[idx_chunk].push(ary_segment_val[idx_pix]);
                }
            }
        }
        return ary_test_val;
    }

    /************************************************************************************************
     * 类型:
     *    函数
     * 功能:
     *    按X,Y相同的N个点分为每段数据
     * 参数:
     *    @param {promises<Array>} all_date 已知走点数据
     * 返回：
     *   @returns {Promise<Array>} 数组
     * 修改:
     *   1. 类型 : 创建
     *      作者 : 徐烁超
     *      时间 : 2020.5.6
     *      内容 : 所有代码
     ************************************************************************************************/
    function mc_split_arr_point(all_date) {
        var arr_date = all_date;
        // 规则段数组
        var arr_out_date = [];
        // 段区域数组
        var arr_set_date = [];
        // 规则状态 0为不明确状态 1为判断X坐标 -1为判断Y坐标
        var ui_rule_start = 0;
        // 规则值 直接通过规则状态获取判断值对比
        var ui_rule_val = -1;
        // 判断值X 储存第一个判断值X坐标
        var ui_jude_x = -1;
        // 判断值Y 储存第一个判断值Y坐标
        var ui_jude_y = -1;

        for (var idx = 0; idx < arr_date.length; idx++) {
            var ui_img_x = arr_date[idx].img_x;
            var ui_img_y = arr_date[idx].img_y;
            var str_color = arr_date[idx].color;

            if ("V" === str_color) {
                arr_set_date.push(arr_date[idx]);
                continue;
            }
            if (-1 === ui_jude_x && -1 === ui_jude_y) {
                ui_jude_x = ui_img_x;
                ui_jude_y = ui_img_y;
                arr_set_date.push(arr_date[idx]);
                continue;
            }
            if (0 === ui_rule_start) {
                if (ui_jude_x === ui_img_x) {
                    ui_rule_start = 1;
                    ui_rule_val = ui_img_x;
                } else if (ui_jude_y === ui_img_y) {
                    ui_rule_start = -1;
                    ui_rule_val = ui_img_y;
                } else {
                    arr_out_date.push(arr_set_date);
                    arr_set_date = [];
                    ui_rule_start = 0;
                    ui_rule_val = -1;
                    ui_jude_x = -1;
                    ui_jude_y = -1;
                }
                arr_set_date.push(arr_date[idx]);
                continue;
            }
            var ui_rule_value = -1;

            if (0 < ui_rule_start) {
                ui_rule_value = ui_img_x;
            }
            if (0 > ui_rule_start) {
                ui_rule_value = ui_img_y;
            }

            if (ui_rule_value !== ui_rule_val) {
                arr_out_date.push(arr_set_date);
                arr_set_date = [];
                ui_rule_start = 0;
                ui_rule_val = -1;
                ui_jude_x = -1;
                ui_jude_y = -1;
            }
            arr_set_date.push(arr_date[idx]);
        }
        arr_out_date.push(arr_set_date);
        return arr_out_date;
    }


    /* **************** 异常处理区域 ********************************************************************* */
    /* 删除多余行扫 */
    function mc_delet_scan_extra() {
        for (var idx_grp = 0; idx_grp < m_ary_dot_data.length; idx_grp++) {
            if (m_ary_dot_data[idx_grp].length < m_ui_scan_cnt) {
                continue;
            }
            var ui_delet_cnt = m_ary_dot_data[idx_grp].length - m_ui_scan_cnt;

            for (var idx_delet = 0; idx_delet < ui_delet_cnt; idx_delet++) {
                m_ary_dot_data[idx_grp].pop();
            }
        }
        return true;
    }
    /* *********************  EXP API  **************************************** */
    /**
     * @param {Promise<Array>} ary_dot 已知走点数据
     * @param {Promise<Function>} fn_callback 回调函数
     * @returns {Promise<Boolean>} 储存结果
     */
    this.mc_util_dot_set_dot_data = function (ary_dot, fn_callback) {
        return mc_set_dot_data(ary_dot, fn_callback);
    };
    /**
     * @param {Promise<Object>} obj_mod_msg 模组基本信息{}
     * @returns {Promise<Boolean>} 存入结果
     */
    this.mc_util_dot_set_mod_msg = function (obj_mod_msg) {
        return mc_set_mod_msg(obj_mod_msg);
    };
    /**
     * @param {Promise<Number>} ui_select_str_idx 指定填充数据线
     * @param {Promise<Function>} fn_callback 回调函数
     * @returns {Promise<Function>} 执行补点命令
     */
    this.mc_util_dot_fill_line = function (ui_select_str_idx, fn_callback) {
        return mc_fill_line(ui_select_str_idx, fn_callback);
    };
    /**
     * @param {Promise<Number>} ui_select_str_idx 指定填充数据线
     * @param {Promise<Function>} fn_callback 回调函数
     * @returns {Promise<Function>} 执行补行命令
     */
    this.mc_util_dot_fill_scan = function (ui_select_str_idx, fn_callback) {
        return mc_fill_scan(ui_select_str_idx, fn_callback);
    };
    /**
     * @param {Promise<Function>} fn_callback 回调函数
     * @returns {Promise<Function>} 执行补组命令
     */
    this.mc_util_dot_fill_grop = function (fn_callback) {
        return mc_fill_grop(fn_callback);
    };
    /**
     * @returns {Promise<Array>} 完成填充后的数组
     */
    this.mc_util_dot_get_dot = function () {
        return m_ary_dot_data;
    };
    /**
     * @returns {Promise<boolean>} 补组结果
     */
    this.mc_util_dot_fill_ok = function () {
        return m_b_fill_ok;
    };
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    填充流程
 * 参数:
 *    @param {promises<String>} str_module_msg 模组基本信息
 *    @param {promises<Array>} ary_dot 已知走点数据
 *    @param {promises<string>} str_info_json 显示芯片注册信息
 *    @param {promises<boolean>} b_is_more 当前走点模式(多线/单线)
 *    @param {promises<Function>} fn_callback 获取数据的回调函数(填充完成的数据)
 *    @param {promises<Number>} ui_scan_len 设置单扫长度(无则使用默认计算值)
 *    @param {promises<Number>} ui_select_str_idx 当前选择数据线 -1代表并行
 * 返回：
 *   NA
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.5.6
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_quick_fill_apply(str_module_msg, ary_dot, str_info_json, b_is_more, fn_callback, ui_scan_len, ui_select_str_idx) {
    if ("function" !== typeof fn_callback) {
        return;
    }
    var obj_sdk_param = new mc_sdk_param();

    if (!obj_sdk_param.set_json(str_module_msg)) {
        fn_callback(false);
        return;
    }
    var obj_mod_msg = {};

    // 模组宽度
    obj_mod_msg.ui_mod_w = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_WEITH"));
    // 模组高度
    obj_mod_msg.ui_mod_h = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_HEIGHT"));
    // 模组设置的行扫数
    obj_mod_msg.ui_scan_cnt = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_SCAN_CNT"));
    // 模组数据组类型
    obj_mod_msg.ui_grp_mod = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_TXGRP_MODE"));
    // 模组数据组数
    obj_mod_msg.ui_grp_cnt = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_TXGRP_CNT"));
    // 获取模组颜色
    obj_mod_msg.ary_color = mc_quick_get_mod_color(obj_sdk_param);
    // 获取模组灯珠数,只有串行模式使用
    obj_mod_msg.ui_led_cnt = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_LED_GRP_MODE"));
    // 显示芯片名称
    var str_dispchip_name = obj_sdk_param.get_param_value("MC_LANG_DISPCHIP_LIST");

    // 显示芯片注册信息
    if (!obj_sdk_param.set_json(str_info_json)) {
        fn_callback();
        return;
    }
    // 模组芯片通道数
    obj_mod_msg.ui_ic_channels = Number(obj_sdk_param.get_attr_val(str_dispchip_name, "IC_CHANNELS"));
    // 模组行长对齐值
    obj_mod_msg.ui_scanalign = Number(obj_sdk_param.get_attr_val(str_dispchip_name, "SCANALIGN"));
    if (isNaN(obj_mod_msg.ui_scanalign) || 0 >= obj_mod_msg.ui_scanalign) {
        obj_mod_msg.ui_scanalign = 1;
    }

    if (!mc_quick_data_is_ok(obj_mod_msg)) {
        fn_callback(false);
        return;
    }

    //  获取模组单扫长度
    obj_mod_msg.ui_scan_len = Math.floor(obj_mod_msg.ui_mod_w * (obj_mod_msg.ui_mod_h / obj_mod_msg.ui_grp_cnt) / obj_mod_msg.ui_scan_cnt);
    if ("number" === typeof ui_scan_len && 0 < ui_scan_len) {
        obj_mod_msg.ui_scan_len = ui_scan_len;
    }

    // 构造补点函数
    var obj_rule_dot = new mc_get_rule_by_dot();

    // 存入模组基本信息
    obj_rule_dot.mc_util_dot_set_mod_msg(obj_mod_msg);
    // 存入模组已知走点信息(解析完成后)
    obj_rule_dot.mc_util_dot_set_dot_data(ary_dot, set_dot_success);
    // 命令函数执行补行
    function set_dot_success() {
        // 命令函数执行补点
        obj_rule_dot.mc_util_dot_fill_line(ui_select_str_idx, fill_line_success);
    }
    // 补行结束后的回调
    function fill_line_success() {
        // 命令函数执行补扫
        obj_rule_dot.mc_util_dot_fill_scan(ui_select_str_idx, fill_scan_success);
    }
    // 补扫结束后的回调
    function fill_scan_success() {
        if (-1 !== ui_select_str_idx) {
            fill_mod_success();
            return;
        }
        // 命令函数执行补组
        obj_rule_dot.mc_util_dot_fill_grop(fill_mod_success);
    }
    // 补组结束后的回调
    function fill_mod_success() {
        var ary_dot_data = obj_rule_dot.mc_util_dot_get_dot();

        ary_dot_data = mc_quick_trans_result(ary_dot_data);
        fn_callback(ary_dot_data, obj_rule_dot.mc_util_dot_fill_ok());
    }
}

// 将补充数组解析为页面数组
function mc_quick_trans_result(ary_fill_data) {
    var ary_return_data = [];


    for (var idx_str = 0; idx_str < ary_fill_data.length; idx_str++) {
        var ary_scan_data = ary_fill_data[idx_str];
        var ui_invalid_cnt = 0;

        ary_return_data.push([]);
        for (var idx_scan = 0; idx_scan < ary_scan_data.length; idx_scan++) {
            var ary_pix_data = ary_scan_data[idx_scan];

            ary_return_data[idx_str].push([]);
            for (var idx_pix = 0; idx_pix < ary_pix_data.length; idx_pix++) {
                var obj_point_data = ary_fill_data[idx_str][idx_scan][idx_pix];

                if (!obj_point_data) {
                    ary_return_data[idx_str][idx_scan].push(obj_point_data);
                    continue;
                }
                if ("V" === obj_point_data.color) {
                    ui_invalid_cnt++;
                    continue;
                }

                var obj_data = {
                    x: obj_point_data.img_x + 1,
                    y: obj_point_data.img_y + 1,
                    invalid_cnt: ui_invalid_cnt,
                    color: obj_point_data.color
                };

                ary_return_data[idx_str][idx_scan].push(obj_data);
                ui_invalid_cnt = 0;
            }
        }
    }
    return ary_return_data;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    判断模组信息是否可用
 * 参数:
 *    @param {promises<Object>} obj_mod_msg 模组基本信息
 * 返回：
 *   @returns {Promise<Boolean>} 模组信息是否可用
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.5.6
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_quick_data_is_ok(obj_mod_msg) {
    if (Array.isArray(obj_mod_msg) || "object" !== typeof obj_mod_msg) {
        return false;
    }
    if (("number" !== typeof obj_mod_msg.ui_mod_w || 0 >= obj_mod_msg.ui_mod_w) ||
        ("number" !== typeof obj_mod_msg.ui_mod_h || 0 >= obj_mod_msg.ui_mod_h) ||
        ("number" !== typeof obj_mod_msg.ui_scan_cnt || 0 >= obj_mod_msg.ui_scan_cnt) ||
        ("number" !== typeof obj_mod_msg.ui_grp_mod || 0 >= obj_mod_msg.ui_grp_mod) ||
        ("number" !== typeof obj_mod_msg.ui_grp_cnt || 0 >= obj_mod_msg.ui_grp_cnt) ||
        ("number" !== typeof obj_mod_msg.ui_ic_channels || 0 >= obj_mod_msg.ui_ic_channels) ||
        ("number" !== typeof obj_mod_msg.ui_scanalign || 0 >= obj_mod_msg.ui_scanalign) ||
        (!Array.isArray(obj_mod_msg.ary_color) || 0 >= obj_mod_msg.ary_color.length)
    ) {
        return false;
    }
    return true;
}

/************************************************************************************************
 * 类型:
 *    函数
 * 功能:
 *    获取模组颜色
 * 参数:
 *    @param {promises<Object>} obj_sdk_param 模组基本信息
 * 返回：
 *   @returns {Promise<Array>} 模组颜色
 * 修改:
 *   1. 类型 : 创建
 *      作者 : 徐烁超
 *      时间 : 2020.5.6
 *      内容 : 所有代码
 ************************************************************************************************/
function mc_quick_get_mod_color(obj_sdk_param) {
    var ui_mod_grp = Number(obj_sdk_param.get_param_value("MC_LANG_LABLE_TXGRP_MODE"));

    if (isNaN(ui_mod_grp)) {
        return false;
    }
    if (1 === ui_mod_grp) {
        ui_mod_grp = 3;
    }
    var ary_color = [];

    for (var idx_color = 1; idx_color <= ui_mod_grp; idx_color++) {
        var str_param_name = "MC_LANG_LABLE_COLOR_" + idx_color;
        var str_clr_val = obj_sdk_param.get_param_value(str_param_name);

        if (!str_clr_val) {
            return false;
        }
        switch (str_clr_val) {
            case "1":
                str_clr_val = "R";
                break;
            case "2":
                str_clr_val = "G";
                break;
            case "3":
                str_clr_val = "B";
                break;
            default:
                str_clr_val = "V";
                break;
        }
        ary_color.push(str_clr_val);
    }
    if (ary_color.length !== ui_mod_grp) {
        return false;
    }
    if (-1 === ary_color.indexOf("R") && -1 === ary_color.indexOf("G") && -1 === ary_color.indexOf("B")) {
        parent.mc_alert_popout("MC_LANG_MC_SET_MOD_CLR_ERR");
        return false;
    }
    return ary_color;
}
